/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2006 * Sleepycat Software. All rights reserved. * * $Id: VerifyUtils.java,v 1.1 2006/05/06 09:01:56 ckaestne Exp $ */ package com.sleepycat.je.cleaner; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import com.sleepycat.je.Database; import com.sleepycat.je.DatabaseException; import com.sleepycat.je.DbInternal; import com.sleepycat.je.dbi.DatabaseImpl; import com.sleepycat.je.dbi.SortedLSNTreeWalker; import com.sleepycat.je.dbi.SortedLSNTreeWalker.TreeNodeProcessor; import com.sleepycat.je.log.LogEntryType; import com.sleepycat.je.utilint.DbLsn; /** * Verify cleaner data structures */ public class VerifyUtils { private static final boolean DEBUG = false; /** * Compare the lsns referenced by a given Database to the lsns held * in the utilization profile. Assumes that the database and * environment is quiescent, and that there is no current cleaner * activity. */ public static void checkLsns(Database db) throws DatabaseException { DatabaseImpl dbImpl = DbInternal.dbGetDatabaseImpl(db); /* Get all the lsns in the database. */ GatherLSNs gatherLsns = new GatherLSNs(); long rootLsn = dbImpl.getTree().getRootLsn(); SortedLSNTreeWalker walker = new SortedLSNTreeWalker(dbImpl, false, // don't remove from INList false, // don't set db state rootLsn, gatherLsns); walker.walk(); Set lsnsInTree = gatherLsns.getLsns(); lsnsInTree.add(new Long(rootLsn)); /* Get all the files used by this database. */ Iterator iter = lsnsInTree.iterator(); Set fileNums = new HashSet(); while (iter.hasNext()) { long lsn = ((Long) iter.next()).longValue(); fileNums.add(new Long(DbLsn.getFileNumber(lsn))); } /* Gather up the obsolete lsns in these file summary lns */ iter = fileNums.iterator(); Set obsoleteLsns = new HashSet(); UtilizationProfile profile = dbImpl.getDbEnvironment().getUtilizationProfile(); while (iter.hasNext()) { Long fileNum = (Long) iter.next(); PackedOffsets obsoleteOffsets = new PackedOffsets(); TrackedFileSummary tfs = profile.getObsoleteDetail(fileNum, obsoleteOffsets, false /* logUpdate */); PackedOffsets.Iterator obsoleteIter = obsoleteOffsets.iterator(); while (obsoleteIter.hasNext()) { long offset = obsoleteIter.next(); Long oneLsn = new Long(DbLsn.makeLsn(fileNum.longValue(), offset)); obsoleteLsns.add(oneLsn); if (DEBUG) { System.out.println("Adding 0x" + Long.toHexString(oneLsn.longValue())); } } } /* Check than none the lsns in the tree is in the UP. */ boolean error = false; iter = lsnsInTree.iterator(); while (iter.hasNext()) { Long lsn = (Long) iter.next(); if (obsoleteLsns.contains(lsn)) { System.err.println("Obsolete lsns contains valid lsn " + DbLsn.getNoFormatString(lsn.longValue())); error = true; } } /* * Check that none of the lsns in the file summary ln is in the * tree. */ iter = obsoleteLsns.iterator(); while (iter.hasNext()) { Long lsn = (Long) iter.next(); if (lsnsInTree.contains(lsn)) { System.err.println("Tree contains obsolete lsn " + DbLsn.getNoFormatString(lsn.longValue())); error = true; } } if (error) { throw new DatabaseException("Lsn mismatch"); } } private static class GatherLSNs implements TreeNodeProcessor { private Set lsns = new HashSet(); public void processLSN(long childLSN, LogEntryType childType) { lsns.add(new Long(childLSN)); } public Set getLsns() { return lsns; } } }